package com.common.test;

import java.util.Set;

import org.apache.log4j.Logger;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Keys;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.NoSuchFrameException;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import com.common.util.RunSettingUtil;

public class OperationBase {
	
	public UITestBase tb;
	
	private String windowhandlepresent = "";
	
	protected Logger log = Logger.getLogger(OperationBase.class);
	
	public OperationBase(UITestBase tb){
		this.tb = tb;
	}
	
    /**
     * 切换到页面最顶层
     */
    public void switchToDefaultContent(){
        WebDriver driver = tb.getDriver();
        driver.switchTo().defaultContent();
    }

    /**
     * 根据frame的名字切换
     * @throws Exception 
     */
    public  void selectFrame(String frameId) throws Exception{
        WebDriver driver = tb.getDriver();
        try {
			driver.switchTo().frame(frameId);
		} catch (NoSuchFrameException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			handlefailure("报错类型为 " + e.getClass().getName() + " 没有'" + frameId + "'这个frameid");
		}
    }

    /**
     * 根据frame的id切换
     * @throws Exception 
     */
    public void selectFrame(int frameId) throws Exception{
        WebDriver driver = tb.getDriver();
        try {
			driver.switchTo().frame(frameId);
		} catch (NoSuchFrameException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			handlefailure("报错类型为 " + e.getClass().getName() + " 没有'" + frameId + "'这个frameid");
		}
    }
    
    /**
     * 鼠标移动到指定控件附近
     * @throws Exception 
     */
    public void movetoelement(DefaultElement defaultElement) throws Exception{
    	WebElement element = null;
    	try {
    		element = defaultElement.getNativeElement();
		} catch (NoSuchElementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			handlefailure("报错类型为 " + e.getClass().getName() + " 页面上不存在控件查找方式为'" + defaultElement.getfindName() + "'，控件查找值为'" + defaultElement.getfindValue() + "'的控件");
		}
    	WebDriver driver = tb.getDriver();
    	Actions action = new Actions(driver);
    	action.moveToElement(element).perform();
    }
    
    /**
     * 模拟鼠标悬停操作
     * @throws Exception 
     */
    public void clickAndHold(DefaultElement defaultElement) throws Exception{
    	WebElement element = null;
    	try {
    		element = defaultElement.getNativeElement();
		} catch (NoSuchElementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			handlefailure("报错类型为 " + e.getClass().getName() + " 页面上不存在控件查找方式为'" + defaultElement.getfindName() + "'，控件查找值为'" + defaultElement.getfindValue() + "'的控件");
		}
    	WebDriver driver = tb.getDriver();
    	Actions action = new Actions(driver);
    	action.clickAndHold(element).perform();
    }
    
    /**
     * 模拟鼠标移动并悬停点击
     * @throws Exception 
     */
    public void movetoelementandclickAndHold(DefaultElement defaultElement) throws Exception{
    	WebElement element = null;
    	try {
    		element = defaultElement.getNativeElement();
		} catch (NoSuchElementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			handlefailure("报错类型为 " + e.getClass().getName() + " 页面上不存在控件查找方式为'" + defaultElement.getfindName() + "'，控件查找值为'" + defaultElement.getfindValue() + "'的控件");
		}
    	WebDriver driver = tb.getDriver();
    	Actions action = new Actions(driver);
    	action.moveToElement(element).clickAndHold(element).perform();
    }
    
    /**
     * 模拟鼠标左键单击动作
     */
    public void actionclick(){
    	WebDriver driver = tb.getDriver();
    	Actions action = new Actions(driver);
    	action.click().perform();
    }
    
    /**
     * 模拟鼠标左键单击控件
     * @throws Exception 
     */
    public void actionclick(DefaultElement defaultElement) throws Exception{
    	WebElement element = null;
    	try {
    		element = defaultElement.getNativeElement();
		} catch (NoSuchElementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			handlefailure("报错类型为 " + e.getClass().getName() + " 页面上不存在控件查找方式为'" + defaultElement.getfindName() + "'，控件查找值为'" + defaultElement.getfindValue() + "'的控件");
		}
    	WebDriver driver = tb.getDriver();
    	Actions action = new Actions(driver);
    	action.click(element).perform();
    }
    
    /**
     * 模拟鼠标左键双击动作
     */
    public void actiondoubleclick(){
    	WebDriver driver = tb.getDriver();
    	Actions action = new Actions(driver);
    	action.doubleClick().perform();
    }
    
    /**
     * 模拟鼠标左键双击控件
     * @throws Exception 
     */
    public void actiondoubleclick(DefaultElement defaultElement) throws Exception{
    	WebElement element = null;
    	try {
    		element = defaultElement.getNativeElement();
		} catch (NoSuchElementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			handlefailure("报错类型为 " + e.getClass().getName() + " 页面上不存在控件查找方式为'" + defaultElement.getfindName() + "'，控件查找值为'" + defaultElement.getfindValue() + "'的控件");
		}
    	WebDriver driver = tb.getDriver();
    	Actions action = new Actions(driver);
    	action.doubleClick(element).perform();
    }
    
    /**
     * 模拟鼠标事件
     */
    public void clickbymouse(Keys key){
    	WebDriver driver = tb.getDriver();
    	Actions action = new Actions(driver);
    	action.sendKeys(key).perform();
    }
    
    /**
     * 模拟键盘按下
     */
    public void keyDown(Keys key){
    	WebDriver driver = tb.getDriver();
    	Actions action = new Actions(driver);
    	action.keyDown(key).perform();
    }
    
    /**
     * 模拟键盘按下抬起
     */
    public void keyDownAndUp(Keys key){
    	WebDriver driver = tb.getDriver();
    	Actions action = new Actions(driver);
    	action.keyDown(key).keyUp(key).perform();
    }
    
    /**
     * 模拟键盘抬起
     */
    public void keyUp(Keys key){
    	WebDriver driver = tb.getDriver();
    	Actions action = new Actions(driver);
    	action.keyUp(key);
    }
    
    /**
     * 记录当前窗口的句柄
     */
    public void recordWindowHandle(){
    	WebDriver driver = tb.getDriver();
    	windowhandlepresent = driver.getWindowHandle();
    }
    
    /**
     * 切换窗口
     */
    public void switchTonewWindow(){
    	WebDriver driver = tb.getDriver();
    	Set<String> windowhandles = driver.getWindowHandles();
    	for(String windowhandle : windowhandles){
    		if(windowhandle.equals(windowhandlepresent)){
    			continue;
    		}else{
    			driver.switchTo().window(windowhandle);
    			break;
    		}
    	}
    }
    
    /**
     * 将滚动条滚到最底部
     */
    public void scrollTo(){  
    	WebDriver driver = tb.getDriver();            
		JavascriptExecutor jse=(JavascriptExecutor) driver;  
        jse.executeScript("window.scrollTo(0, document.body.scrollHeight)");
    }
    
    /**
     * 滚动条滚动到该元素所在处
     * @throws Exception 
     */
    public void scrollTo(DefaultElement defaultElement) throws Exception{
    	WebElement element = null;
    	try {
    		element = defaultElement.getNativeElement();
		} catch (NoSuchElementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			handlefailure("报错类型为 " + e.getClass().getName() + " 页面上不存在控件查找方式为'" + defaultElement.getfindName() + "'，控件查找值为'" + defaultElement.getfindValue() + "'的控件");
		}
    	WebDriver driver = tb.getDriver();            
		JavascriptExecutor jse=(JavascriptExecutor) driver;  
		jse.executeScript("arguments[0].scrollIntoView(true);", element);
    }
    
    public void refresh(){
    	WebDriver driver = tb.getDriver(); 
    	driver.navigate().refresh();
    }
    
    /**
     * 看页面上是否含有指定字符串，赋给一个boolean值 
     */
    public boolean isPageContainsStr(String str){
    	log.info("查看页面上是否存在该字符串" + str);
    	WebDriver driver = tb.getDriver();
    	return driver.getPageSource().contains(str);
    }
    
    /**
     * 判断页面上指定控件是否存在
     */
    public boolean isPresent(DefaultElement defaultElement){
        try{
            defaultElement.getNativeElement();
            return true;
        }catch (NoSuchElementException e){
        	log.info("控件 findName:'" + defaultElement.getfindName() + "' findValue:'" + defaultElement.getfindValue() + "' 不存在");
            return false;
        }
    }

    public boolean waitPageRefresh(DefaultElement defaultElement) {
        WebDriver driver = tb.getDriver();
        return new WebDriverWait(driver, RunSettingUtil.WAITTIME).until(new ExpectedCondition<Boolean>() {
        	boolean isRefresh = false;
        	@Override
            public Boolean apply(WebDriver d) {
            	try{
            		defaultElement.getNativeElement().getTagName();
            	}catch (StaleElementReferenceException e){
            		pause(800);
            		isRefresh = true;
            	}
            	return isRefresh;
            }
        });
	}
    
    /**
     * 在所设置的超时时间内看页面上是否出现指定字符串，过了超时时间
     * 还未出现指定字符串的，就报超时异常
     * @throws Exception 
     */
    public boolean waitForPageContainsStr(final String str) throws Exception{
    	WebDriver driver = tb.getDriver();
        try {
			return new WebDriverWait(driver, RunSettingUtil.WAITTIME).until(new ExpectedCondition<Boolean>() {
			    @Override
			    public Boolean apply(WebDriver d) {
			        return d.getPageSource().contains(str);
			    }
			});
		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			handlefailure("直到超时时间，页面上还是没有出现'" + str + "'这个字符串");
			return false;
		}
    }
    
    /**
     * 在所设置的超时时间内看页面上是否不出现指定字符串，过了超时时间
     * 还是出现指定字符串的，就报超时异常
     * @throws Exception 
     */
    public boolean waitForPageNotContainsStr(final String str) throws Exception{
        WebDriver driver = tb.getDriver();
        try {
			return new WebDriverWait(driver, RunSettingUtil.WAITTIME).until(new ExpectedCondition<Boolean>() {
			    @Override
			    public Boolean apply(WebDriver d) {
			        return !d.getPageSource().contains(str);
			    }
			});
		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			handlefailure("直到超时时间，页面上还是出现'" + str + "'这个字符串");
			return false;
		}
    }

    /**
     * 在所设置的超时时间内看页面上是否存在指定的控件，过了超时时间
     * 还未存在该指定控件的，就报超时异常
     * @throws Exception 
     */
    public boolean waitForElementExist(final DefaultElement defaultElement) throws Exception{
        WebDriver driver = tb.getDriver();
        try {
			return new WebDriverWait(driver, RunSettingUtil.WAITTIME).until(new ExpectedCondition<Boolean>() {
			    @Override
			    public Boolean apply(WebDriver d) {
			    	return defaultElement.getNativeElement()!=null;
			    }
			});
		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			handlefailure("直到超时时间，findname为'" + defaultElement.getfindName() + "'，findValue为 '" + defaultElement.getfindValue() + "'的控件在页面上不存在");
			return false;
		}
    }
    
    /**
     * 在所设置的超时时间内看指定控件是否可视，过了超时时间
     * 指定控件还未可视的，就报超时异常
     * @throws Exception 
     */
    public boolean waitForElementDisplayed(final DefaultElement defaultElement) throws Exception{
    	WebDriver driver = tb.getDriver();
    	try {
			return new WebDriverWait(driver, RunSettingUtil.WAITTIME).until(new ExpectedCondition<Boolean>() {
			    @Override
			    public Boolean apply(WebDriver d) {
			    	return defaultElement.getNativeElement().isDisplayed();
			    }
			});
		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			handlefailure("直到超时时间，findname为'" + defaultElement.getfindName() + "'，findValue为 '" + defaultElement.getfindValue() + "'的控件在页面上不可视");
			return false;
		}
    }
    
    /**
     * 在所设置的超时时间内看指定控件是否不可视，过了超时时间
     * 指定控件还是可视的，就报超时异常
     * @throws Exception 
     */
    public boolean waitForElementNotDisplayed(final DefaultElement defaultElement) throws Exception{
    	WebDriver driver = tb.getDriver();
    	try {
			return new WebDriverWait(driver, RunSettingUtil.WAITTIME).until(new ExpectedCondition<Boolean>() {
			    @Override
			    public Boolean apply(WebDriver d) {
			    	return !defaultElement.getNativeElement().isDisplayed();
			    }
			});
		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			handlefailure("直到超时时间，findname为'" + defaultElement.getfindName() + "'，findValue为 '" + defaultElement.getfindValue() + "'的控件在页面上依然可视");
			return false;
		}
    }
    
    /**
     * 在所设置的超时时间内指定控件上是否出现指定字符串，过了超时时间
     * 指定控件上还是没有出现指定字符串的，就报超时异常
     * @throws Exception 
     */
    public boolean waitForElementTextContainsStr(final DefaultElement defaultElement, final String str) throws Exception{
        WebDriver driver = tb.getDriver();
        try {
			return new WebDriverWait(driver, RunSettingUtil.WAITTIME).until(new ExpectedCondition<Boolean>() {
			    @Override
			    public Boolean apply(WebDriver d) {
			    	return defaultElement.getNativeElement().getText().contains(str);
			    }
			});
		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			handlefailure("直到超时时间，findname为'" + defaultElement.getfindName() + "'，findValue为 '" + defaultElement.getfindValue() + "'的控件上存在'" + str + "'这个字符串");
			return false;
		}
    }
    
    /**
     * 在所设置的超时时间内指定控件是否为不可编辑，过了超时时间
     * 指定控件还是可编辑的，就报超时异常
     * @throws Exception 
     */
    public boolean waitForElementDisabled(DefaultElement defaultElement) throws Exception{
        WebDriver driver = tb.getDriver();
        try {
			return new WebDriverWait(driver, RunSettingUtil.WAITTIME).until(new ExpectedCondition<Boolean>() {
			    @Override
			    public Boolean apply(WebDriver d) {
			    	return !defaultElement.getNativeElement().isEnabled();
			    }
			});
		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			handlefailure("直到超时时间，findname为'" + defaultElement.getfindName() + "'，findValue为 '" + defaultElement.getfindValue() + "'的控件在页面上依然可编辑");
			return false;
		}
    }
    
    /**
     * 后台系统，在所设置的超时时间内指定链接是否为active状态表示链接处于被点击的状态，过了超时时间
     * 指定链接状态不为active没有处于被点击的状态，就报超时异常
     * @throws Exception 
     */
	public boolean waitForPageLinkclicked(DefaultElement defaultElement) throws Exception{
        WebDriver driver = tb.getDriver();
        try {
			return new WebDriverWait(driver, RunSettingUtil.WAITTIME).until(new ExpectedCondition<Boolean>() {
			    @Override
			    public Boolean apply(WebDriver d) {
			    	try {
						return defaultElement.getAttribute("class").equals("active");
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					return null;
			    }
			});
		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			handlefailure("直到超时时间，findname为'" + defaultElement.getfindName() + "'，findValue为'" + defaultElement.getfindValue() + "'的链接不处于active状态");
			return false;
		}
	}
	
    /**
     * 直到控件处于可点击的状态
     * @throws Exception 
     */
	public boolean waitForElementelementToBeClickable(DefaultElement defaultElement) throws Exception{
        WebDriver driver = tb.getDriver();
        try {
			return new WebDriverWait(driver, RunSettingUtil.WAITTIME).until(new ExpectedCondition<Boolean>() {
			    @Override
			    public Boolean apply(WebDriver d) {
			    	ExpectedConditions.elementToBeClickable(defaultElement.getNativeElement());
			    	return true;
			    }
			});
		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			handlefailure("直到超时时间，findname为'" + defaultElement.getfindName() + "'，findValue为 '" + defaultElement.getfindValue() + "'的控件依然不能点击");
			return false;
		}
	}
    
    /**
     * 防止页面刷新使控件无法点击的解决方法
     * @throws Exception 
     */
    public void elementToBeClickable(DefaultElement defaultElement) throws Exception{
    	WebElement element = null;
    	try {
    		element = defaultElement.getNativeElement();
		} catch (NoSuchElementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			handlefailure("报错类型为 " + e.getClass().getName() + " 页面上不存在控件查找方式为'" + defaultElement.getfindName() + "'，控件查找值为'" + defaultElement.getfindValue() + "'的控件");
		}
    	ExpectedConditions.elementToBeClickable(element);
    }
    
    /**
     * 防止页面刷新使控件无法选择的解决方法
     * @throws Exception 
     */
    public void elementToBeSelected(DefaultElement defaultElement) throws Exception{
    	WebElement element = null;
    	try {
    		element = defaultElement.getNativeElement();
		} catch (NoSuchElementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			handlefailure("报错类型为 " + e.getClass().getName() + " 页面上不存在控件查找方式为'" + defaultElement.getfindName() + "'，控件查找值为'" + defaultElement.getfindValue() + "'的控件");
		}
    	ExpectedConditions.elementToBeSelected(element);
    }
    
    /**
     * 设置等待时间
     */
    public void pause(long millseconds){
    	try {
			Thread.sleep(millseconds);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
    /**
     * 抛出异常
     */
    public void handlefailure(String msg) throws Exception{
    	throw new Exception(msg);
    }
}
